package com.hengpeng.itfin.domain.partner.chinapnr;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;

import javax.servlet.ServletRequest;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;

import com.hengpeng.itfin.domain.partner.chinapnr.util.KeyTool;

public class Huifu{
	private static final String VERSION_10 = "10";
	private static final String VERSION_20 = "20";
	
	private static final String CMDID_USER_REGISTER= "UserRegister"; //用户开户,页面浏览器方式
	private static final String CMDID_BG_REGISTER= "BgRegister"; //后台用户开户,后台数据流方式
	private static final String CMDID_USER_BIND_CARD= "UserBindCard"; //用户绑卡,页面浏览器方式
	private static final String CMDID_BG_BIND_CARD= "BgBindCard"; //后台接口绑卡,后台数据流方式
	private static final String CMDID_USER_LOGIN= "UserLogin"; //用户登录,页面浏览器方式
	private static final String CMDID_ACCT_MODIFY= "AcctModify"; //账户信息修改,页面浏览器方式
	private static final String CMDID_CORP_REGISTER= "CorpRegister"; //类型企业开户接口,页面浏览器方式
	private static final String CMDID_DEL_CARD= "DelCard"; //删除银行卡接口,后台数据流方式
	private static final String CMDID_NET_SAVE= "NetSave"; //网银充值,页面浏览器方式
	private static final String CMDID_POS_WH_SAVE= "PosWhSave"; //商户无卡代扣充值,后台数据流方式
	private static final String CMDID_USR_FREEZE_BG= "UsrFreezeBg"; //资金（货款）冻结,后台数据流方式
	private static final String CMDID_USR_UN_FREEZE= "UsrUnFreeze"; //资金（货款）解冻,后台数据流方式
	private static final String CMDID_INITIATIVE_TENDER= "InitiativeTender"; //主动投标,页面浏览器方式
	private static final String CMDID_AUTO_TENDER= "AutoTender"; //自动投标,后台数据流方式
	private static final String CMDID_TENDER_CANCLE= "TenderCancle"; //投标撤销,页面浏览器方式
	private static final String CMDID_AUTO_TENDER_PLAN= "AutoTenderPlan"; //自动投标计划,页面浏览器方式
	private static final String CMDID_AUTO_TENDER_PLAN_CLOSE= "AutoTenderPlanClose"; //自动投标关闭,页面浏览器方式
	private static final String CMDID_LOANS= "Loans"; //自动扣款（放款）,后台数据流方式
	private static final String CMDID_REPAYMENT= "Repayment"; //自动扣款（还款）,后台数据流方式
	private static final String CMDID_TRANSFER= "Transfer"; //转账（商户用）,后台数据流方式
	private static final String CMDID_CASH_AUDIT= "CashAudit"; //取现复核,后台数据流方式
	private static final String CMDID_CASH= "Cash"; //取现,页面浏览器方式
	private static final String CMDID_USR_ACCT_PAY= "UsrAcctPay"; //用户账户支付,页面浏览器方式
	private static final String CMDID_MER_CASH= "MerCash"; //商户代取现接口,后台数据流方式
	private static final String CMDID_USR_TRANSFER= "UsrTransfer"; //前台用户间转账接口,页面浏览器方式
	private static final String CMDID_CREDIT_ASSIGN= "CreditAssign"; //债权转让接口,页面浏览器方式
	private static final String CMDID_AUTO_CREDIT_ASSIGN= "AutoCreditAssign"; //自动债权转让接口,后台数据流方式
	private static final String CMDID_FSS_TRANS= "FssTrans"; //生利宝交易接口,页面浏览器方式
	private static final String CMDID_QUERY_BALANCE= "QueryBalance"; //余额查询(页面),页面浏览器方式
	private static final String CMDID_QUERY_BALANCE_BG= "QueryBalanceBg"; //余额查询(后台),后台数据流方式
	private static final String CMDID_QUERY_ACCTS= "QueryAccts"; //商户子账户信息查询,后台数据流方式
	private static final String CMDID_QUERY_TRANS_STAT= "QueryTransStat"; //交易状态查询,后台数据流方式
	private static final String CMDID_QUERY_TENDER_PLAN= "QueryTenderPlan"; //自动投标计划状态查询,后台数据流方式
	private static final String CMDID_RECONCILIATION= "Reconciliation"; //投标对账(放款和还款对账),后台数据流方式
	private static final String CMDID_TRF_RECONCILIATION= "TrfReconciliation"; //商户扣款对账,后台数据流方式
	private static final String CMDID_CASH_RECONCILIATION= "CashReconciliation"; //取现对账,后台数据流方式
	private static final String CMDID_QUERY_ACCT_DETAILS= "QueryAcctDetails"; //账户明细查询,页面浏览器方式
	private static final String CMDID_SAVE_RECONCILIATION= "SaveReconciliation"; //充值对账,后台数据流方式
	private static final String CMDID_QUERY_RETURN_DZ_FEE= "QueryReturnDzFee"; //垫资手续费返还查询,后台数据流方式
	private static final String CMDID_CORP_REGISTER_QUERY= "CorpRegisterQuery"; //担保类型企业开户状态查询接口,后台数据流方式
	private static final String CMDID_CREDIT_ASSIGN_RECONCILIATION= "CreditAssignReconciliation"; //债权查询接口,后台数据流方式
	private static final String CMDID_FSS_PURCHASE_RECONCILIATION= "FssPurchaseReconciliation"; //生利宝转入对账接口,后台数据流方式
	private static final String CMDID_FSS_REDEEM_RECONCILIATION= "FssRedeemReconciliation"; //生利宝转出对账接口,后台数据流方式
	private static final String CMDID_QUERY_FSS= "QueryFss"; //生利宝产品信息查询,后台数据流方式
	private static final String CMDID_QUERY_FSS_ACCTS= "QueryFssAccts"; //生利宝账户信息查询,后台数据流方式
	private static final String CMDID_QUERY_CARD_INFO= "QueryCardInfo"; //银行卡查询接口,后台数据流方式
	
	// 汇付应答签数据key列表
	public static final String[] VERIFY_KYES_USER_REGISTER= {"CmdId","RespCode","MerCustId", "UsrId", "UsrCustId", "BgRetUrl", "TrxId", "RetUrl", "MerPriv"};
	public static final String[] VERIFY_KEYS_NET_SAVE= {"CmdId","RespCode","MerCustId","UsrCustId","OrdId","OrdDate","TransAmt","TrxId","RetUrl","BgRetUrl","MerPriv"};
	public static final String[] VERIFY_KEYS_TRANSFER= {"CmdId", "RespCode","OrdId","OutCustId","OutAcctId","TransAmt","InCustId","InAcctId","RetUrl","BgRetUrl","MerPriv"};
	public static final String[] VERIFY_KEYS_QUERY_ACCT={"CmdId", "RespCode","MerCustId"};
	
	private String merId;
	private String serverLocation;
	private KeyTool keyTool;

/*	public Huifu(String merId, String serverLocation, KeyTool kt){
		this.merId= merId;
		this.serverLocation= serverLocation;
		this.keyTool= kt;
	}
*/	
	public Huifu(){
	}
	
	public Huifu(String merId, String serverLocation, String privateKey, String publicKey){
		this.merId= merId;
		this.serverLocation= serverLocation;
		this.keyTool= new KeyTool(privateKey, publicKey);	
	}
	
	private class ParamLinker{
		private List<NameValuePair> params= new ArrayList <NameValuePair>();;
		
		public ParamLinker append(String key, String value){
			if(key!=null && value != null)
				params.add(new BasicNameValuePair(key, value));
			return this;
		}
		
		public List<NameValuePair> getParams(){
			return this.params;
		}
	}
	
	private class ParamHash{
		private HashMap<String, String> params= new HashMap<String, String>();
		
		public ParamHash append(String key, String value){
			if(key!=null && value != null)
				params.put(key, value);
			
			return this;
		}
		
		public HashMap<String, String> getParams(){
			return this.params;
		}
	}
	
	private class StringLinker{
		private String buffer="";
		
		public StringLinker append(String str){
			if(str != null)
				this.buffer+= str;
			
			return this;
		}
		
		public String getBuffer(){
			return this.buffer;
		}	
		public String toString(){
			return this.buffer;
		}
	}
	
/*	private JSONObject reactResponse(String response, String[] verifyList) throws HuifuException{
		JSONObject obj= (JSONObject)JSON.parse(response);

		if(this.verifySign(obj, verifyList)){
			return obj;
		}else{
			throw new HuifuException();
		}
	}*/
	
	/**
	 * @desc	应答验签方法
	 * @param response
	 * @param verifyList
	 * @return
	 */
/*	public boolean verifySign(JSONObject response, String[] verifyList){
		if(response.isEmpty() || verifyList==null)return false;
		
		String plaintStr= "";
		for(String i:verifyList){
			plaintStr+= (String)response.get(i);
		}	
		
		return keyTool.verifySign(plaintStr, (String)response.get("ChkValue"));
	}
	
	public boolean verifySign(ServletRequest request, String[] verifyKeys){
		Enumeration<String> paramNames= (Enumeration<String>) request.getParameterNames();
		String pName="";
		JSONObject req2JSON= new JSONObject();
		while(paramNames.hasMoreElements()){
			pName= paramNames.nextElement();
			req2JSON.put(pName, request.getParameter(pName));
		}
		
		return this.verifySign(req2JSON, verifyKeys);
	}*/
	
	public String request(List<NameValuePair> params){	
		String respStr="";
		try{			
			CloseableHttpClient httpclient = HttpClients.createDefault();
			HttpPost httpPost = new HttpPost(this.serverLocation);
			httpPost.setEntity(new UrlEncodedFormEntity(params));
			CloseableHttpResponse response2 = httpclient.execute(httpPost);		
			
			try {		
			    //System.out.println(response2.getStatusLine());
			    HttpEntity entity2 = response2.getEntity();
			    // do something useful with the response body
			    // and ensure it is fully consumed
			    respStr= EntityUtils.toString(entity2);
			    EntityUtils.consume(entity2);
			}finally {
				response2.close();
			}
		}catch(IOException e){
			e.printStackTrace();
		}
		return respStr;	
	}
		
	/**
	 * @desc  用户注册，页面需要跳转
	 * @param bgRetUrl
	 * @param retUrl
	 * @param usrId
	 * @param usrName
	 * @param idType
	 * @param idNo
	 * @param usrMp
	 * @param usrEmail
	 * @param merPriv
	 * @param charSet
	 * @return
	 */
	public HashMap<String, String> userRegister(String bgRetUrl, String retUrl,
			String usrId, String usrName, String idType, String idNo, String usrMp,
			String usrEmail, String merPriv, String charSet){
		//request sign content
		StringLinker sl= new StringLinker();
		sl.append(VERSION_10).append(CMDID_USER_REGISTER).append(this.merId).append(bgRetUrl).append(retUrl)
			.append(usrId).append(usrName).append(idType).append(idNo).append(usrMp).append(usrEmail).append(merPriv);

		String checkValue= keyTool.signMessage(sl.getBuffer());

		ParamHash pl= new ParamHash();
		pl.append("Version", VERSION_10)
		  .append("CmdId", CMDID_USER_REGISTER)
		  .append("MerCustId", merId)
		  .append("BgRetUrl", bgRetUrl)
		  .append("UsrId", usrId)
		  .append("ChkValue", checkValue)
		  .append("RetUrl", retUrl)
		  .append("UsrName", usrName)
		  .append("IdType", idType)
		  .append("IdNo", idNo)
		  .append("UsrMp", usrMp)
		  .append("UsrEmail", usrEmail)
		  .append("MerPriv", merPriv)
		  .append("CharSet", charSet);
					
		return pl.getParams();
	}
	
	public HashMap<String, String> userBindCard(String usrCustId, String bgRetUrl, String merPriv){
		StringLinker sl= new StringLinker();
		sl.append(VERSION_10)
			.append(CMDID_USER_BIND_CARD)
			.append(this.merId)
			.append(usrCustId)
			.append(bgRetUrl)
			.append(merPriv);
		
		String checkValue= keyTool.signMessage(sl.getBuffer());

		ParamHash pl= new ParamHash();
		pl.append("Version", VERSION_10)
			.append("CmdId", CMDID_USER_BIND_CARD)
			.append("MerCustId", this.merId)
			.append("UsrCustId", usrCustId)
			.append("BgRetUrl", bgRetUrl)
			.append("MerProv", merPriv)
			.append("ChkValue", checkValue);
		
		return pl.getParams();
	}

	public HashMap<String, String> userLogin(String usrCustId){ 
		// USerLogin 1 
		StringLinker sl= new StringLinker();
		sl.append(VERSION_10)
			.append(CMDID_USER_LOGIN)
			.append(this.merId)
			.append(usrCustId);
		
		String checkValue= keyTool.signMessage(sl.getBuffer());

		ParamHash pl= new ParamHash();
		pl.append("Version", VERSION_10)
			.append("CmdId", CMDID_USER_LOGIN)
			.append("MerCustId", this.merId)
			.append("UsrCustId", usrCustId)
			.append("ChkValue", checkValue);
		
		return pl.getParams();		
	}
	
	public HashMap<String, String> netSave(String usrCustId, String ordId, String ordDate,
			String gateBusiId, String openBankId, String dcFlag, String transAmt,
			String retUrl, String bgRetUrl, String openAcctId, String certId,
			String merPriv){
		// NetSave 1
		// USerLogin 1 
		StringLinker sl= new StringLinker();
		sl.append(VERSION_10)
			.append(CMDID_BG_BIND_CARD)
			.append(this.merId)
			.append(usrCustId)
			.append(ordId)
			.append(ordDate)
			.append(gateBusiId)
			.append(openBankId)
			.append(dcFlag)
			.append(transAmt)
			.append(retUrl)
			.append(bgRetUrl)
			.append(openAcctId)
			.append(certId)
			.append(merPriv);
		
		String checkValue= keyTool.signMessage(sl.getBuffer());

		ParamHash pl= new ParamHash();
		pl.append("Version", VERSION_10)
			.append("CmdId", CMDID_BG_BIND_CARD)
			.append("MerCustId", this.merId)
			.append("UsrCustId", usrCustId)
			.append("ChkValue", checkValue);
		
		return pl.getParams();			
	} 
	
	public  void initiativeTender(){
		// InitialtiveTender 2
	}
	
	public void loans(){
		// Loans 2 
	}
	
	public void repayment(){
		// Repayment 2
	}
	
	/*public JSONObject transfer(String ordId, String outAcctId, String transAmt, String inAcctId, String bgRetUrl, String merPriv ) throws HuifuException{
		//request sign content
		StringLinker sl= new StringLinker();
		sl.append(VERSION_10).append(CMDID_TRANSFER).append(ordId).append(this.merId)
			.append(outAcctId).append(transAmt).append(this.merId).append(inAcctId).append("")
			.append(bgRetUrl).append(merPriv);
		String checkValue= keyTool.signMessage(sl.getBuffer());
		
		ParamLinker pl= new ParamLinker();
		pl.append("Version", VERSION_10)
		  .append("CmdId", CMDID_TRANSFER)
		  .append("OrdId", ordId)
		  .append("OutCustId", this.merId)
		  .append("OutAcctId", outAcctId)
		  .append("TransAmt", transAmt)
		  .append("InCustId", this.merId)
		  .append("InAcctId", inAcctId)
		  .append("RetUrl", null)
		  .append("BgRetUrl", bgRetUrl)
		  .append("MerPriv", merPriv)
		  .append("ChkValue", checkValue);
		
		return reactResponse(request(pl.getParams()), this.VERIFY_KEYS_TRANSFER);
	}*/
	
	public void cash(){
		// Cash 2
	}
	
	public void addBidInfo(){
		// AddBidInfo 1
	}
	
	public void queryBalanceBg(){
		// QueryBlanceBg  1
	}
		
	/**
	 * @desc 获取商户子账户信息
	 * @return
	 * @throws HuifuException
	 * @throws IOException 
	 */
	/*public JSONObject querySubAccounts() throws HuifuException{
		//request sign content
		StringLinker sl= new StringLinker();
		sl.append(VERSION_10).append(CMDID_QUERY_ACCTS).append(this.merId);
		String checkValue= keyTool.signMessage(sl.getBuffer());
		
		ParamLinker pl= new ParamLinker();
		pl.append("Version", VERSION_10).append("CmdId", CMDID_QUERY_ACCTS)
		  .append("MerCustId", merId).append("ChkValue", checkValue);
				
		return reactResponse(request(pl.getParams()), VERIFY_KEYS_QUERY_ACCT);
	}*/
	
	public String getMerId() {
		return merId;
	}

	public void setMerId(String merId) {
		this.merId = merId;
	}

	public String getServerLocation() {
		return serverLocation;
	}

	public void setServerLocation(String serverLocation) {
		this.serverLocation = serverLocation;
	}

	public KeyTool getKeyTool() {
		return keyTool;
	}

	public void setKeyTool(KeyTool keyTool) {
		this.keyTool = keyTool;
	}

	public void queryTransStat(){
		// QueryTransStat 1 
	}
	
	public void trfReconciliation(){
		// TrfReconciliation 1 
	}
	
	public void reconciliation(){
		// Reconciliation 1
	}
	
	public void cashReconciliation(){
		// CashReconciliation 2
	}
	
	public void saveReconciliation(){
		// SaveReconciliation 1
	}
}